package com.elysia.visionmanagerspringboot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.elysia.visionmanagerspringboot.domain.dto.AddResolutionDTO;
import com.elysia.visionmanagerspringboot.domain.dto.VideoDTO;
import com.elysia.visionmanagerspringboot.domain.entity.Video;
import com.elysia.visionmanagerspringboot.domain.entity.VideoResolution;
import com.elysia.visionmanagerspringboot.domain.vo.VideoVO;
import com.elysia.visionmanagerspringboot.enumeration.ResourceTypeEnum;
import com.elysia.visionmanagerspringboot.mapper.VideoMapper;
import com.elysia.visionmanagerspringboot.properties.AliyunMtsProperties;
import com.elysia.visionmanagerspringboot.result.Result;
import com.elysia.visionmanagerspringboot.service.IVideoResolutionService;
import com.elysia.visionmanagerspringboot.service.IVideoService;
import com.elysia.visionmanagerspringboot.untils.AliyunMtsUtil;
import com.elysia.visionmanagerspringboot.untils.AliyunOssUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

@RequiredArgsConstructor
@Service
@Slf4j
public class IVideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements IVideoService {
    private final AliyunOssUtil aliyunOssUtil;
    private final AliyunMtsUtil aliyunMtsUtil;
    private final AliyunMtsProperties aliyunMtsProperties;
    private final IVideoResolutionServiceImpl videoResolutionService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> update(VideoDTO videoDTO) throws Exception {
        // 前置校验：resolutions 非空且所有分辨率均已配置
        List<String> inputResolutions = videoDTO.getResolutions();
        // 校验分辨率列表非空
        if (inputResolutions == null || inputResolutions.isEmpty()) {
            throw new IllegalArgumentException("请选择至少一个目标分辨率");
        }
        // 校验每个分辨率都在后端配置中存在
        Set<String> supportedResolutions = aliyunMtsProperties.getTemplate().keySet();
        for (String resolution : inputResolutions) {
            if (!supportedResolutions.contains(resolution)) {
                throw new IllegalArgumentException("不支持的分辨率：" + resolution + "，当前支持的分辨率为：" + supportedResolutions);
            }
        }
        String fileKey = null;
        List<String> generatedResolutionKeys = new ArrayList<>(); // 记录已生成的分辨率文件Key
        try {
            // 1. 上传源视频，记录fileKey
            fileKey = aliyunOssUtil.uploadFile(videoDTO.getFile(), ResourceTypeEnum.VIDEO);

            // 2. 保存源视频信息
            Video video = Video.builder()
                    .fileKey(fileKey)
                    .alt(videoDTO.getAlt())
                    .caption(videoDTO.getCaption())
                    .build();
            save(video);

            // 3. 转码并收集分辨率记录，同时记录已生成的OSS文件Key
            List<VideoResolution> resolutionList = new ArrayList<>();
            for (String resolution : videoDTO.getResolutions()){
                String targetFileKey = aliyunMtsUtil.convertVideoResolution(fileKey, resolution);
                generatedResolutionKeys.add(targetFileKey); // 记录已转码成功的文件Key
                resolutionList.add(VideoResolution.builder()
                        .videoId(video.getId())
                        .resolution(resolution)
                        .fileKey(targetFileKey)
                        .build());
            }

            // 4. 批量保存分辨率记录
            boolean saveBatchSuccess = videoResolutionService.saveBatch(resolutionList);
            if (!saveBatchSuccess) {
                throw new RuntimeException("批量保存分辨率记录失败");
            }
            return Result.success();
        } catch (Exception e) {
            // 5. 异常时手动删除OSS文件（回滚外部资源）
            if (fileKey != null) {
                try {
                    aliyunOssUtil.deleteFile(fileKey); // 删除源视频
                } catch (Exception deleteE) {
                    log.error("删除源视频OSS文件失败，fileKey: {}", fileKey, deleteE);
                }
            }
            for (String resKey : generatedResolutionKeys) {
                try {
                    aliyunOssUtil.deleteFile(resKey); // 删除已生成的分辨率文件
                } catch (Exception deleteE) {
                    log.error("删除分辨率OSS文件失败，resKey: {}", resKey, deleteE);
                }
            }
            throw e; // 重新抛出异常，触发数据库事务回滚
        }
    }

    @Override
    public Result<Object> getList() {
        log.info("获取视频列表");
        // 1. 查询所有视频
        List<Video> list = list();
        List<VideoVO> result = new ArrayList<>();
        // 2. 遍历视频列表，获取每个视频的分辨率信息
        for (Video video : list) {
            // 3. 获取每个视频的分辨率信息
            List<VideoResolution> resolutions = videoResolutionService.getByVideoId(video.getId());
            HashMap<String, String> resolutionMap = new HashMap<>();
            for (VideoResolution resolution : resolutions)
                resolutionMap.put(resolution.getResolution(), aliyunOssUtil.getFileUrl(resolution.getFileKey(), 3600));
            result.add(VideoVO.builder()
                    .id(video.getId())
                    .url(resolutionMap)
                    .alt(video.getAlt())
                    .caption(video.getCaption())
                    .build());
        }
        return Result.success(result);
    }

    @Override
    public Result<Object> delete(Long id) {
        Video video = getById(id);
        aliyunOssUtil.deleteFile(video.getFileKey());
        removeById(id);
        return Result.success();
    }

    @Override
    public Result<Object> delete(Long id, String resolution) {
        VideoResolution videoResolution = videoResolutionService.getByVideoIdAndResolution(id, resolution);
        aliyunOssUtil.deleteFile(videoResolution.getFileKey());
        videoResolutionService.removeById(videoResolution.getId());
        return Result.success();
    }

    @Override
    public Result<Object> addResolution(Long id, AddResolutionDTO addResolutionDTO) throws Exception {
        Video video = getById(id);
        String fileKey = video.getFileKey();
        List<VideoResolution> resolutionList = new ArrayList<>();
        List<String> generatedResolutionKeys = new ArrayList<>();
        try {
            for (String resolution : addResolutionDTO.getResolutions()){
                String targetFileKey = aliyunMtsUtil.convertVideoResolution(fileKey, resolution);
                generatedResolutionKeys.add(targetFileKey); // 记录已转码成功的文件Key
                resolutionList.add(VideoResolution.builder()
                        .videoId(video.getId())
                        .resolution(resolution)
                        .fileKey(targetFileKey)
                        .build());
            }

            // 4. 批量保存分辨率记录
            boolean saveBatchSuccess = videoResolutionService.saveBatch(resolutionList);
            if (!saveBatchSuccess) {
                throw new RuntimeException("批量保存分辨率记录失败");
            }
            return Result.success();
        } catch (Exception e) {
            for (String resKey : generatedResolutionKeys) {
                try {
                    aliyunOssUtil.deleteFile(resKey); // 删除已生成的分辨率文件
                } catch (Exception deleteE) {
                    log.error("删除分辨率OSS文件失败，resKey: {}", resKey, deleteE);
                }
            }
            throw e;
        }
    }
}
